<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <title>COMP332 Obr Translation into RISC Code</title>
  </head>

  <body>
    <h1>Department of Computing, Macquarie University</h1>
    <h2>COMP332 Obr Translation into RISC Code</h2>

    This document describes
    
    <UL>
    <LI>the structure of the target trees used by the Obr compiler to represent
        RISC target programs,
    <LI>the appropriate target constructs for the translation of each Obr source
        construct, and
    <LI>how to get Obr to generate and run RISC machine code.
    </UL>
    
    <P>The document concludes with examples of translations of a couple of
    simple Obr programs.</P>
    
    <P>The code that supports the tree structure and encoding described in
    this document can be found in <code>RISCTree.scala</code> and
    <code>Encoder.scala</code> in the Obr compiler.  The mapping from Obr
    trees to RISC trees can be found in <code>Transformation.scala</code>.</p>

    <h2>The RISC Target Program Tree</h2>
    
    <p>All of the information that the translation task of the compiler
    provides about the target program is embodied in the target
    program tree.  If a particular item of information cannot be
    accessed via this tree, then it cannot be obtained at all.
    Information is encoded in the "shape" of the tree and in values
    stored at the leaves.</p>

      <p>This section defines the set of possible target program trees by
      defining all of the concepts and constructs of the target
      language.</p>

    <h3>RISC Concepts</h3>

    <h4>Datum</h4>

    <p>A datum is a construct yielding an explicit value that can be
    stored or used as an operand for other operations. The encoder
    uses the attribute <code>reg</code> to associate a local machine
    register with each Datum to provide storage for the Datum's
    value; hence the transformation phase does not have to perform
    register allocation.</p>

    <h4>Item</h4>

    <p>An item is a construct that does not yield a value.</p>

    <h3>RISC Constructs</h3>

    <p>A RISCProg node represents a complete RISC program.
    This RISCProg node is the root of the target program tree,
    and never appears in any other position.</p>

    <p>The following productions summarise the constructs of the RISC by
    giving the structure of the subtree for each construct.</p>
    
<pre>
RISCProg:        RISCNode: Item+

Beq:             Item: Datum Label
Bne:             Item: Datum Label
Jmp:             Item: Label
LabelDef:        Item: Label
Read:            Item: Address
Ret:             Item
StW:             Item: Address Datum
Write:           Item: Datum

AddW:            Datum: Datum Datum
Cond:            Datum: Datum Datum Datum
CmpeqW:          Datum: Datum Datum
CmpneW:          Datum: Datum Datum
CmpgtW:          Datum: Datum Datum
CmpltW:          Datum: Datum Datum
DivW:            Datum: Datum Datum
IntDatum:        Datum: Int
LdW:             Datum: Address
MulW:            Datum: Datum Datum
NegW:            Datum: Datum
Not:             Datum: Datum
RemW:            Datum: Datum Datum
SubW:            Datum: Datum Datum
SequenceDatum:   Datum: Item+ Datum

Local:           Address: Int
Indexed:         Address: Local Datum
</pre>

    <p>The "W" in some of the node names means that those operations
    operate on word-sized values (four bytes on the RISC) which in
    this compiler are used to implement both integer and Boolean
    values.</p>

    <p>The following subsections describe the constructs of the table.
    Some of those constructs represent specific RISC instructions and
    others represent collections of instructions that involve related
    decisions about operand access.</p>

    <h4>RISC</h4>
    
<pre>
RISC:     RISC: Item+
</pre>

  <p>The encoding of a RISC construct is very simple, we simply encode each of the items in its body, concatenate the resulting RISC code sequences and then add <em>prologue</em> (initilisation) and <em>epilogue</em> (termination) code. Currently this prologue code simply initialises register $27 topoints to the memory segment which will be used to store the values of global variables and temporaries. The epilogue is begun by a standard label to enable the <code>Ret</code> construct (see below) to transfer control to it. Then it simply terminates the program by executing a <code>ret $0</code> instruction.</p>

    <h4>Branches</h4>
    
<pre>
Beq:       Item: Datum Label
Bne:       Item: Datum Label
Jmp:       Item: Label
</pre>

    <p>A branch (<code>Beq</code> or <code>Bne</code>) is encoded as the encoding of its <em>Datum</em> component followed by a test and branch to the <em>Label</em> component. A <code>Beq</code> does a branch on equal to zero and a <code>Bne</code> does a branch on not equal to zero.</p>
    
     <p>A <code>Jmp</code> does an unconditional branch to its <em>Label</em> component.</p>

    <h4><code>LabelDef</code></h4>

<pre>
LabelDef:  Item: Label
</pre>
    
  <p>A <code>LabelDef</code> construct represents a definition of a label and is encoded by emitting that definition in the appropriate assembler syntax.</p>
        
    <h4><code>Read</code> and <code>Write</code></h4>

<pre>
Read:      Item: Address
Write:     Item: Datum
</pre>

  <p>These constructs are encoded using the corresponding terminal IO RISC instructions <code>rd</code>, <code>wrd</code> and <code>wrl</code>.  In the case of <code>Read</code> the value read is stored in the location given by the <em>Address</em> component.  In the case of <code>Write</code> the value written is that given by the <em>Datum</em> component which is encoded first.</p>
        
        <h4><code>Ret</code></h4>
        
<pre>
Ret:       Item
</pre>            

  <p>A <code>Ret</code> construct is encoded by an unconditional jump to a label at the end of the code comprising the program (i.e., to the beginning of the epilogue). This encoding ensures that a return from any part of the program will complete necessary processing before exiting the program.</p>

        <h4><code>StW</code></h4>

<pre>
StW:       Item: Address Datum
</pre>

        <p>A <code>StW</code> construct is encoded by encoding the <em>Datum</em> component followed by an instruction to store the value of the <em>Datum</em> into the given address.</p>

        <h4>Arithmetic operations: <code>AddW</code>, <code>DivW</code>, <code>MulW</code>, <code>NegW</code>, <code>Not</code>, <code>RemW</code>, <code>SubW</code></h4>

<pre>
AddW:      Datum: Datum Datum
DivW:      Datum: Datum Datum
MulW:      Datum: Datum Datum
NegW:      Datum: Datum
RemW:      Datum: Datum Datum
SubW:      Datum: Datum Datum
</pre>

    <p>Most of the arithmetic operations are encoded by encoding their <em>Datum</em> component(s) followed by a single instruction that performs the appropriate operation. The <code>NegW</code> operation is implemented by subtracting the given operand from 0 (the value of register $0). </p>

<h4>IntDatum</h4>

<pre>
IntDatum:  Datum: Int
</pre>

    <p>An IntDatum construct is encoded as a move of the integer value
    into the location required by the <em>Datum</em>.</p>

<h4><code>Cond</code> and <code>Not</code></h4>
        
<pre>
Cond:      Datum: Datum Datum Datum
Not:       Datum: Datum
</pre>

    <p>A <code>Cond</code> construct is encoded by encoding its first <em>Datum</em> component, followed by a sequence of instructions that evaluate the second <em>Datum</em> if the first <em>Datum</em> is non-zero, or evaluate the third <em>Datum</em> if the first <em>Datum</em> is zero. In either case the result value will be left in the location required by the <code>Cond</code> <em>Datum</em> itself. The <code>Not</code> construct is encoded as if it were converted to a corresponding <code>Cond</code> tree under the following translation: </p>
        
<pre>
Not (d) -&gt; Cond (d, IntDatum(0), IntDatum(1))
</pre>

        <h4>Comparisons: <code>CmpeqW</code>, <code>CmpneW</code>, <code>CmpgtW</code>, <code>CmpltW</code></h4>
        
<pre>
CmpeqW:    Datum: Datum Datum
CmpneW:    Datum: Datum Datum
CmpgtW:    Datum: Datum Datum
CmpltW:    Datum: Datum Datum
</pre>

    <p>The comparison constructs <code>CmpeqW</code>, <code>CmpgtW</code>, <code>CmpltW</code>, and <code>CmpneW</code> are encoded as the encoding of their operands, followed by a comparison instruction, followed by moves and conditional branches as appropriate to establish the result value of 0 or 1 in the register associated with the given comparison Datum.</p>

        <h4><code>LdW</code></h4>

<pre>
LdW:       Datum: Address
</pre>

    <p>A <code>LdW</code> construct is encoded as a load of a word value from the location specified by its <em>Address</em> component into the register associated with this <code>LdW</code>.</p>
    
        <h4>Addresses: <code>Local</code>, <code>Indexed</code></h4>
    
<pre>
Local:     Address: Int
Indexed:   Address: Local Datum
</pre>        
    

    <p>A <code>Local</code> address represents a word-sized storage location in the main block of memory that is accessible to an Obr program. Its <code>Int</code> child specifies the offset in bytes from the start of the memory block at which the word is located.</p>

 <p>An <code>Indexed</code> address is an address that is computed as a byte offset from a local address. The offset is given by a computation expressed as a Datum.</p>

 <p>When an address is used in another construct (i.e., an <code>LdW</code> or an <code>StW</code>) it is first encoded, then used as an operand in the load or store. <code>Local</code> address do not produce any code when they are encoded. <code>Indexed</code> addresses encode their Datum component.</p>

    <h4><code>SequenceDatum</code></h4>

    A <code>SequenceDatum</code> construct of the form
    
<pre>
SequenceDatum Item-1 ... Item-n Datum
</pre>

    is implemented as follows:

<pre>
Code for Item-1
...
Code for Item-n
Code for Datum
</pre>

    Here <code>Item-i</code> is the ith element of the component <em>Item</em> list.

    <h2>Transforming Obr Source Trees to RISC Target Trees</h2>
    
    <p>The results of the mapping process from source to target are reflected in the properties and structure of the target tree. This section describes how Obr source data and actions are mapped to target constructs.</p>
    
    <h3>Obr/RISC Data Mapping</h3>

    <p>Obr programs can manipulate only integer and Boolean basic values plus structured values that are arrays and records. Both parameters and variables can be declared. Therefore, a definition of the data mapping task must specify how values of these types are implemented on the RISC, and how storage is allocated for parameters and variables.</p>

    <p>Because there is no possibility of recursion in Obr, it is possible to implement data storage for parameters and variables statically. The Obr "parameters" really aren't parameters at all --- they are top-level variables that must be initialised by reading them from the standard input before executing the body of the Obr program. Thus their storage is implemented just like variables.</p>

      <p>Obr constants do not need any storage since the compiler knows their value and can construct an <code>IntDatum</code> node that can be used directly.</p>

    <p>An Obr integer is implemented by a RISC word (32 bits). For convenience, Boolean values are also represented by RISC words. True is represented by 1, and false is represented by 0.</p>
    
     <p>Storage for all of the variables declared in an Obr program is allocated in a single area of RISC memory. During execution, register $27 contains the address of the beginning of the memory area. Thus, any variable's location can be specified by the sum of a non-negative integer and the contents of register $27. Since each variable occupies four bytes of memory, the offsets from the content of register $27 are all multiples of 4: The topmost variable is in location $27, the next variable is in location $27 + 4, and so on.</p>
    
     <p>Arrays and records are allocated as contiguous memory as if the array elements or fields were declared as individual integer variables. (Recall that array elements and fields must be integers.) Therefore an array of N elements or a record with N fields is allocated as N contiguous words of memory.</p>

    <h3>Obr/RISC Action Mapping</h3>

    Most of the Obr constructs map to RISC constructs in an obvious way. Some constructs do not generate any code (e.g, constructs like <code>IntVar</code> and <code>ArrayVar</code> that represent declarations). This section describes how the other constructs are translated into RISC target tree constructs.<p>

    <h4>Assignment</h4>

    <p><code>AssignStmt</code> constructs are translated into a <code>StW</code> construct whose left child is the address of the variable, array element or field being assigned, and whose right child is the translation of the expression on the right-hand side of the assignment.</p>

 <h4>Boolean Expressions and Operations</h4>

 <p>A <code>BoolExp</code> is translated into an <code>IntDatum</code> where 0 is used for <code>FALSE</code> and 1 for <code>TRUE</code>.</p>

    <p><code>AndExp</code> and <code>OrExp</code> translate into uses of the <code>Cond</code> target construct in order to achieve short-circuit evaluation. They are translated as follows:</p>

<pre>
AndExp (e1, e2) -&gt; Cond (t1, t2, 0)
OrExp (e1, e2) -&gt; Cond (t1, 1, t2)
</pre>

    <p>In both of these translations <code>t1</code> and <code>t2</code> are the translations of <code>e1</code> and <code>e2</code>, respectively.</p>

 <p><code>NotExp</code> translates into a boolean complement operation using the <code>Not</code> target construct.</p>

    <h4>Comparison Operations</h4>

    <p>The comparison operators <code>EqualExp</code>, <code>NotEqualExp</code>, <code>GreaterExp</code>, and <code>LessExp</code> are translated to the <code>CmpeqW</code>, <code>CmpneW</code>, <code>CmpgtW</code> and <code>CmpltW</code> constructs, respectively.</p>

    <h4><code>ExitStmt</code></h4>

    <p>An <code>ExitStmt</code> is implemented by a jump to the terminating label of the closest containing <code>LoopStmt</code>. See also the description of the <code>LoopStmt</code> construct below.</p>

 <h4><code>FieldExp</code></h4>

 <p>A <code>FieldExp</code> translates to a <code>LdW</code> from the address of the given record field.</p>

    <h4><code>ForStmt</code></h4>

    <p>A <code>ForStmt</code> construct is implemented as follows:</p>

<pre>
ForStmt (id, e1, e2, s) -&gt;
    StW (idmem, t1),
    StW (mem, t2),
    Bne (CmpgtW (LdW (idmem), LdW (mem)), L2),
    Jmp (L1),
    LabelDef (L3),
    StW (idmem, AddW (LdW (idmem), IntDatum (1))),
    LabelDef (L1),
    i
    Bne (CmpltW (LdW (idmem), LdW (mem)), L3),
    LabelDef (L2)
</pre>

    <p>Here, <code>i</code> is the list of <em>Item</em> nodes that is the translation of <code>s</code>, <code>t1</code> is the translation of <code>e1</code>, and <code>t2</code> is the translation of <code>e2</code>. <code>idmem</code> is the storage location being used for the variable <code>id</code>, and <code>mem</code> is a new integer memory location not used elsewhere.</p>

    <p>Note that this scheme avoids a problem if the maximum expression <code>e2</code> evaluates to the maximum integer possible, because <code>id</code> is not incremented unless overflow cannot happen.</p>

    <h4><code>IdnExp</code></h4>

 <p>An <code>IdnExp</code> is translated into either an <code>IntDatum</code> containing the integer value of the identifier (if it denotes a constant), or a <code>LdW</code> from the location in which the variable is stored.</p>

    <h4><code>IfStmt</code></h4>

    <p>An <code>IfStmt</code> construct is implemented as follows:</p>

<pre>
IfStmt (e, s1, s2) -&gt;
    Beq (t, L1)
    i1
    Jmp (L2)
    LabelDef (L1)
    i2
    LabelDef (L2)
</pre>

        <p>Here, <code>i1</code> and <code>i2</code> are the lists of <em>Item</em> nodes that are the translations of <code>s1</code> and <code>s2</code>, respectively, and <code>t</code> is the translation of <code>e</code>.</p>

    <h4><code>IndexExp</code></h4>

    <p>An <code>IndexExp</code> translates to a <code>LdW</code> from the address of the given array element. In general, the index is not constant so it must be calculated as part of the address computation.</p>

    <h4>Integer Expressions and Arithmetic Operations</h4>

 <p>An <code>IntExp</code> is translated into an <code>IntDatum</code> whose value is the <code>Int</code> component of the <code>IntExp</code>.</p>

    <p>The arithmetic target constructs are used to implement the arithmetic operators (<code>MinusExp</code>, <code>NegExp</code>, <code>ModExp</code>, <code>PlusExp</code>, <code>SlashExp</code> and <code>StarExp</code>) in the obvious way. For example, <code>PlusExp</code> is represented by <code>AddW</code>, <code>ModExp</code> by <code>RemW</code>, and <code>NegExp</code> by <code>NegW</code>.</p>

    <h4><code>IntParam</code></h4>

    <p>Parameter declarations are always represented by <code>IntParam</code> constructs and are translated into a <code>Read</code> construct whose child is address of the storage allocated to the parameter.</p>

    <h4><code>LoopStmt</code></h4>

    <p>A <code>LoopStmt</code> construct is implemented as follows:</p>

<pre>
Loop (s) -&gt;
    LabelDef (L1)
    i
    Jmp (L1)
    LabelDef (L2)
</pre>

    <p>Here, <code>i</code> is the list of <em>Item</em> nodes that is the translation of <code>s</code>. <code>L2</code> is a label that can be used as the destination of jumps implementing <code>ExitStmt</code> constructs within the loop.</p>

    <h4><code>ObrInt</code></h4>

    <p>The <code>ObrInt</code> construct is translated into a RISC construct whose children are the <em>Item</em> nodes comprising the translation of its <em>Declaration</em> and <em>Statement</em> components. The RISC node also is given an <code>Int</code> component to record the maximum size of storage used by the program.</p>

    <h4><code>ReturnStmt</code></h4>

    <p>The <code>ReturnStmt</code> construct is implemented by a <code>Write</code> construct whose child is the translation of the component <em>Expression</em> to be returned, followed by a <code>Ret</code> construct.</p>

    <h4><code>WhileStmt</code></h4>

    The <code>WhileStmt</code> construct is implemented as follows:

<pre>
WhileStmt (e, s) -&gt;
    Jmp (L1)
    LabelDef (L2)
    i
    LabelDef (L1)
    Bne (t, L2)
</pre>

    <p>Here, <code>i</code> is the list of <em>Item</em> nodes that is the translation of <code>s</code>, and <code>t</code> is the translation of <code>e</code>.</p>

    <h2>Running Compiled Programs</h2>

    <p>The default behaviour of the Obr compiler is to execute all syntactic, semantic and code generation phases, reporting any errors that occur but doing nothing else. To alter this behaviour we provide three command line flags:</p>
    
    <ul>
        <li><p><code>-t</code> spill the target tree constructed by the translation phase to the standard output.</p></li>
        <li><p><code>-a</code> spill the output of the encoding phase to the standard output as RISC assembly language code.</p></li>
        <li><p><code>-e</code> assemble and execute the generated RISC code in the Obr compilers built in RISC machine emulator.</p></li>
    </ul>
    
    <h3>Detailed Examples</h3>
    
    <p>This section shows the complete RISC target trees and assembly code that
    would be produced for the factorial and GCD Obr programs.</p>

<p>Consider the Obr version of Euclid's algorithm for calculating the greatest
    common divisor of two numbers. </p>

<pre>
PROGRAM GCD (x : INTEGER; y : INTEGER) : INTEGER;

BEGIN
    WHILE x # y DO
        IF x > y
            THEN x := x - y;
            ELSE y := y - x;
        END
    END
    RETURN x;
END GCD.
</pre>

<p>From this code, the Obr compiler generates the following target tree:</p>

<pre>
RISCProg(
    List(
        StW(Local(0),Read()), 
        StW(Local(4),Read()), 
        Jmp(Label(2)), 
        LabelDef(Label(3)), 
        Beq(CmpgtW(LdW(Local(0)),LdW(Local(4))),Label(4)),
        StW(Local(0),SubW(LdW(Local(0)),LdW(Local(4)))), 
        Jmp(Label(5)), 
        LabelDef(Label(4)), 
        StW(Local(4),SubW(LdW(Local(4)),LdW(Local(0)))), 
        LabelDef(Label(5)), 
        LabelDef(Label(2)), 
        Bne(CmpneW(LdW(Local(0)),LdW(Local(4))),Label(3)), 
        Write(LdW(Local(0))), 
        Ret()))
</pre>

<p>From this target tree, the encoder produces the following RISC assembly code. Note that the encoder includes the target constructs as comments (starting with exclamation marks) to make the correspondence clearer.</p>

<pre>
    ! Prologue
    movi $27, $0, 0
    ! StW(Local(0),Read())
    rd $1
    stw $1, $27, 0
    ! StW(Local(4),Read())
    rd $1
    stw $1, $27, 4
    ! Jmp(Label(2))
    br label2
    ! LabelDef(Label(3))
label3:
    ! Beq(CmpgtW(LdW(Local(0)),LdW(Local(4))),Label(4))
    ldw $1, $27, 0
    ldw $2, $27, 4
    cmp $1, $2
    movi $1, $0, 1
    bgt label7
    movi $1, $0, 0
label7:
    cmpi $1, 0
    beq label4
    ! StW(Local(0),SubW(LdW(Local(0)),LdW(Local(4))))
    ldw $1, $27, 0
    ldw $2, $27, 4
    sub $1, $1, $2
    stw $1, $27, 0
    ! Jmp(Label(5))
    br label5
    ! LabelDef(Label(4))
label4:
    ! StW(Local(4),SubW(LdW(Local(4)),LdW(Local(0))))
    ldw $1, $27, 4
    ldw $2, $27, 0
    sub $1, $1, $2
    stw $1, $27, 4
    ! LabelDef(Label(5))
label5:
    ! LabelDef(Label(2))
label2:
    ! Bne(CmpneW(LdW(Local(0)),LdW(Local(4))),Label(3))
    ldw $1, $27, 0
    ldw $2, $27, 4
    cmp $1, $2
    movi $1, $0, 1
    bne label8
    movi $1, $0, 0
label8:
    cmpi $1, 0
    bne label3
    ! Write(LdW(Local(0)))
    ldw $1, $27, 0
    wrd $1
    wrl
    ! Ret()
    br label6
    ! Epilogue
label6:
    ret $0
</pre>

   <P>Here is the same information for the Obr factorial program.</P>
   
<pre>
PROGRAM Factorial (v : INTEGER) : INTEGER;

CONST
    limit = 7;

VAR
    c : INTEGER;
    fact : INTEGER;

BEGIN
    IF (v &lt; 0) OR (v &gt; limit) THEN
        RETURN -1;
    ELSE
        c := 0;
        fact := 1;
        WHILE c &lt; v DO
            c := c + 1;
            fact := fact * c;
        END
        RETURN fact;
    END
END Factorial.
</pre>

   <p>From this code, the Obr compiler generates the following target tree:</p>

<pre>
RISCProg(
    List(
        StW(Local(0),Read()), 
        Beq(
            Cond(
                CmpltW(LdW(Local(0)),IntDatum(0)),
                IntDatum(1),
                CmpgtW(LdW(Local(0)),IntDatum(7))),
            Label(2)),
        Write(NegW(IntDatum(1))), 
        Ret(), 
        Jmp(Label(3)), 
        LabelDef(Label(2)), 
        StW(Local(4),IntDatum(0)), 
        StW(Local(8),IntDatum(1)), 
        Jmp(Label(4)), 
        LabelDef(Label(5)), 
        StW(Local(4),AddW(LdW(Local(4)),IntDatum(1))), 
        StW(Local(8),MulW(LdW(Local(8)),LdW(Local(4)))), 
        LabelDef(Label(4)), 
        Bne(CmpltW(LdW(Local(4)),LdW(Local(0))),Label(5)), 
        Write(LdW(Local(8))), 
        Ret(), 
        LabelDef(Label(3))))
</pre>

   <p>From this target tree, the encoder produces the following RISC assembly code:</p>

<pre>
    ! Prologue
    movi $27, $0, 0
    ! StW(Local(0),Read())
    rd $1
    stw $1, $27, 0
    ! Beq(Cond(CmpltW(LdW(Local(0)),IntDatum(0)),IntDatum(1),CmpgtW(LdW(Local(0)),IntDatum(7))),Label(2))
    ldw $1, $27, 0
    movi $2, $0, 0
    cmp $1, $2
    movi $1, $0, 1
    blt label9
    movi $1, $0, 0
label9:
    cmpi $1, 0
    beq label7
    movi $1, $0, 1
    mov $1, $0, $1
    br label8
label7:
    ldw $1, $27, 0
    movi $2, $0, 7
    cmp $1, $2
    movi $1, $0, 1
    bgt label10
    movi $1, $0, 0
label10:
    mov $1, $0, $1
label8:
    cmpi $1, 0
    beq label2
    ! Write(NegW(IntDatum(1)))
    movi $1, $0, 1
    sub $1, $0, $1
    wrd $1
    wrl
    ! Ret()
    br label6
    ! Jmp(Label(3))
    br label3
    ! LabelDef(Label(2))
label2:
    ! StW(Local(4),IntDatum(0))
    movi $1, $0, 0
    stw $1, $27, 4
    ! StW(Local(8),IntDatum(1))
    movi $1, $0, 1
    stw $1, $27, 8
    ! Jmp(Label(4))
    br label4
    ! LabelDef(Label(5))
label5:
    ! StW(Local(4),AddW(LdW(Local(4)),IntDatum(1)))
    ldw $1, $27, 4
    movi $2, $0, 1
    add $1, $1, $2
    stw $1, $27, 4
    ! StW(Local(8),MulW(LdW(Local(8)),LdW(Local(4))))
    ldw $1, $27, 8
    ldw $2, $27, 4
    mul $1, $1, $2
    stw $1, $27, 8
    ! LabelDef(Label(4))
label4:
    ! Bne(CmpltW(LdW(Local(4)),LdW(Local(0))),Label(5))
    ldw $1, $27, 4
    ldw $2, $27, 0
    cmp $1, $2
    movi $1, $0, 1
    blt label11
    movi $1, $0, 0
label11:
    cmpi $1, 0
    bne label5
    ! Write(LdW(Local(8)))
    ldw $1, $27, 8
    wrd $1
    wrl
    ! Ret()
    br label6
    ! LabelDef(Label(3))
label3:
    ! Epilogue
label6:
    ret $0
</pre>
   
    <hr>
    <address><a href="mailto:asloane@comp.mq.edu.au">Tony Sloane</a> and <a href="mailto:domv@ics.mq.edu.au">Dominic Verity</a></address>
<!-- Created: Thu Jul  9 11:51:06 EST 1998 -->
<!-- hhmts start -->Last Modified: Tue Oct 05 16:10:03 +1100 2010<!-- hhmts end -->
<br>
<a href="http://www.mq.edu.au/legalstuff.html">Copyright (c) 1998-2012 by
Macquarie University. All rights reserved.</A></FONT><BR>
  </body>
</html>
